﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MonsterEngine;
using MonsterEngine.Interfaces;
using MonsterEngine.Managers;
using MonsterEngine.Entities;

namespace MonsterMash
{
    public class Program
    {
        public static WorldManager wManager = new WorldManager();
        private static Account _userAccount;
        private static Account _vsAccount;
        private static int _lastActiveHash;

        static void Main(string[] args)
        {
            _vsAccount = CreateSteveAccount(); // Test Account;

            CreateAccountOrLogin();
        }

        static void CreateAccountOrLogin()
        {
            Console.WriteLine("1: Login");
            Console.WriteLine("2: Create Account");

            string resp = Console.ReadLine();

            if (resp == "2")
            {
                CreateNewAccount();
                CreateAccountOrLogin();
            }
            else
            {

                if (LoginToAccount())
                {
                    ShowActionMenu();
                }
            }
        }

        private static bool LoginToAccount()
        {
            AccountManager aMan = new AccountManager();
            Console.WriteLine("Account Name?");
            Account acct = aMan.GetAccount(Console.ReadLine());

            if (acct == null)
            {
                Console.WriteLine("Account not found!");
                return false;
            }
            _userAccount = acct;
            return true;
        }

        private static void ShowActionMenu()
        {
            // Either fight or create toon
            Console.WriteLine("What to do?");
            Console.WriteLine("1: Set active toon");
            Console.WriteLine("2: Start a fight");
            Console.WriteLine("3: Create toon");

            string action = Console.ReadLine();

            switch (action)
            {
                case "1":
                    SelectActiveCharacter();
                    ShowActionMenu();
                    break;
                default:
                    StartAFight();
                    break;
            }
        }

        private static void SelectActiveCharacter()
        {
            Console.WriteLine("Select fighter (type char id number)");
            _userAccount.Fighters.ForEach(f =>
                {
                    Console.WriteLine("{0} - {1}", f.CharId, f.Name); // Strange to pick the ID, but will be cool on web.
                });
            _lastActiveHash = int.Parse(Console.ReadLine()); // NEED TO VALIDATE! Otherwise super-duper-hack-a-sar
        }

        private static void StartAFight()
        {
            while (DoFight())
            {

            }
        }

        private static bool CreateNewAccount()
        {
            Account newAccount = new Account();
            newAccount.Fighters = new List<IFightable>();
            Character fighter = new Character();

            fighter.AbilityList = new List<IAbilities>();
            fighter.BuffList = new List<IAugmentable>();

            Console.WriteLine("Account Name?");
            newAccount.Name = Console.ReadLine();

            Console.WriteLine("Fighter Name?");
            fighter.Name = Console.ReadLine();
            fighter.isActive = true;
            fighter.MaxDamage = 5;
            fighter.MinDamage = 1;
            fighter.Level = 1;

            CreateStats(ref fighter);
            CreateAbilities(ref fighter);

            newAccount.Fighters.Add(fighter);

            return DisplayAccountReview(newAccount);
        }

        static void CreateStats(ref Character fighter)
        {
            int statLeft = 5;
            //Stats
            while (statLeft > 0)
            {
                Console.WriteLine("Select a stat to increase ({0} remaining points)", statLeft);
                Console.WriteLine("1: Max Damage");
                Console.WriteLine("2: Physical Defense");
                Console.WriteLine("3: Magical Defense");
                Console.WriteLine("4: Attack Power");
                Console.WriteLine("5: Spell Power");
                int selection = int.Parse(Console.ReadLine());
                if (IncreaseStat(ref fighter, selection))
                {
                    statLeft--;
                }
            }
        }

        static void CreateAbilities(ref Character fighter)
        {
            // Abilities
            if (!SelectAbility(ref fighter)) // Keep asking them until they select something
            {
                SelectAbility(ref fighter);
            }
        }

        static bool DisplayAccountReview(Account newAccount)
        {
            Console.WriteLine("Account Name: {0}", newAccount.Name);
            Character toon = (Character)newAccount.Fighters[0];
            Console.WriteLine("Toon Name: {0}", toon.Name);

            Console.WriteLine("Max Damage: {0}", toon.MaxDamage);
            Console.WriteLine("Physical Defense: {0}", toon.PhysicalDefense);
            Console.WriteLine("Magical Defense: {0}", toon.MagicalDefense);
            Console.WriteLine("Attack Power: {0}", toon.AttackPower);
            Console.WriteLine("Spell Power: {0}", toon.SpellPower);

            toon.AbilityList.ForEach(a =>
                {
                    Console.WriteLine("Ability: {0}", a.Name);
                });
            Console.WriteLine("Create account?");
            if ("y" == Console.ReadLine())
            {
                AccountManager dbManager = new AccountManager();
                while(!dbManager.InsertAccount(newAccount)) // No WAY OUT!?!?!!?
                {
                    newAccount.Name = PickNewName();
                }
                return true;
            }
            return false;
        }

        static string PickNewName()
        {
            Console.WriteLine("Name taken, choose another!");
            return Console.ReadLine();
        }

        static bool IncreaseStat(ref Character fighter, int selection)
        {
            switch (selection)
            {
                case 1:
                    fighter.MaxDamage++;
                    break;
                case 2:
                    fighter.PhysicalDefense++;
                    break;
                case 3:
                    fighter.MagicalDefense++;
                    break;
                case 4:
                    fighter.AttackPower++;
                    break;
                case 5:
                    fighter.SpellPower++;
                    break;
                default:
                    return false;   
            }
            return true;
        }

        static bool SelectAbility(ref Character fighter)
        {
            Console.WriteLine("Select an ability");
            List<IAbilities> aList = new AbilityManager().BuildAllAbilities();
            aList.ForEach(a =>
                {
                    Console.WriteLine("{0} - {1}", a.AbilityKey, a.Name);
                });
            int selectedAbilityKey = int.Parse(Console.ReadLine());

            IAbilities selectedAbility = aList.Where(a => a.AbilityKey == selectedAbilityKey).First();

            if (selectedAbility != null)
            {
                fighter.AbilityList.Add(selectedAbility);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Accounts for testing...should always fight Steve
        /// </summary>
        #region Dummy Accounts
        static Account CreateLeoAccount()
        {
            Account leoAccount = new Account();
            leoAccount.Fighters = new List<IFightable>();
            leoAccount.Name = "Leo";

            Character hero = new Character();
            hero.CharId = 1;
            hero.isActive = true;
            hero.Level = 1;
            hero.Name = "Leo";
            hero.MaxDamage = 5;
            hero.MinDamage = 1;
            hero.MagicalDefense = 1;
            hero.PhysicalDefense = 1;
            hero.AttackPower = 0;
            hero.SpellPower = 1;
            hero.Experience = 1;
            hero.AbilityList = new AbilityManager().BuildAllAbilities();
            hero.BuffList = new List<IAugmentable>();
            leoAccount.Fighters.Add(hero);

            return leoAccount;
        }
        static Account CreateSteveAccount()
        {
            Account steveAccount = new Account();
            steveAccount.Fighters = new List<IFightable>();
            steveAccount.Name = "Steve";

            Character monster = new Character();
            monster.CharId = 2;
            monster.isActive = true;
            monster.HitPoints = 30;
            monster.Level = 1;
            monster.Name = "Steve";
            monster.MaxDamage = 7;
            monster.MinDamage = 1;
            monster.MagicalDefense = 1;
            monster.PhysicalDefense = 4;
            monster.AttackPower = 2;
            monster.SpellPower = 0;
            monster.Experience = 2;
            monster.AbilityList = new List<IAbilities>();
            monster.BuffList = new List<IAugmentable>();
            steveAccount.Fighters.Add(monster);
            return steveAccount;
        }
        #endregion Dummy Accounts

        /// <summary>
        /// This will be removed for "Challenges"
        /// </summary>
        /// <returns></returns>
        static bool DoFight()
        {
            ResetForFight();

            wManager.Player1 = _userAccount.Fighters.Single(s => s.CharId == _lastActiveHash);
            wManager.Player2 = _vsAccount.Fighters[0];
            wManager.StartFight();

            Console.WriteLine("Do again?");

            string doAgain = Console.ReadLine();
            if (doAgain == "y")
                return true;
            return false;
        }

        /// <summary>
        /// This will go away once the values for levels are driven from the DB
        /// </summary>
        static void ResetForFight()
        {
            _userAccount.Fighters.Single(s => s.CharId == _lastActiveHash).HitPoints = 30;
            _vsAccount.Fighters[0].HitPoints = 30;
        }
    }
}
